INSTRUCTIONS:

  • Use the onstage arrows or arrow keys to scroll up and down.
  • Read the case study and answer the questions at the bottom.

Click here to view this as a Google Doc including cited sources.

To navigate the page using the TAB key, first press ESC to exit the code editor.

title_text = "Case Study: Attack! Vectors & Surface" text = ''' The Dark Overlord contacts your school and demands payment in Bitcoin - or else they'll release student information (or worse)! This sounds like the plot of a bad movie, but in 2017, this really happened to a school district in Columbia Falls, Montana. And although they may have been one of the first, they're not alone! In December of 2020, the FBI issued a warning that showed a nearly 30% increase in ransomware attacks against schools.\n Remote-learning made schools even more vulnerable to cyber attacks. Shadowy criminal hacker groups terrorized schools by hacking into school networks and demanding huge ransom payments, threatening terrible consequences if they weren't paid. In 2021, hackers demanded $40 million from a Florida school district. After the district offered to pay a smaller amount instead, the hackers published thousands of the district's stolen files. How do schools become victims of ransomware attacks? Hackers use attack vectors against the attack surface!\n An attack vector is a way of gaining unauthorized access to a network or computer system. When hackers "hack into" a device or network, they use an attack vector. Attack vectors include weak passwords, out-of-date software, and links or files that download malicious (harmful) code. The attack surface is ALL of the attack vectors that could be used. You can think of it as all the weak points in your system! Software (like Zoom or Microsoft Teams), computers, network devices, and even teachers and students are all part of the attack surface. Surprisingly, people are the largest attack surface, and the weakest link! People can be tricked into visiting dangerous sites, running code, or sharing login information. This can give hackers access.\n What can you do to stop cybercriminals? You've already started! Learning about cybersecurity and digital citizenship will make you a stronger, smarter cyber consumer. ''' # Questions and options dictionary # FORMAT: "question text": (correct_answer_number, [list of answer options]) question_to_options = { "Threatening to publish or destroy data unless a payment is received is called a:": (3, ["attack vector" ,"attack surface", "ransomware attack", "publishing attack"]), "The FBI reported that there was a nearly ______ in this type of attack against schools.": (3, ["10%", "20%", "30%", "70%"]), "What is the definition of an attack vector?": (4, ["all the weak points in a computer/networking system", "hacker groups such as The Dark Overlord", "malicious code", "a way of gaining unauthorized access to a network or computer system"]), "What is the attack surface?": (1, ["all the weak points in a computer/networking system", "hacker groups such as The Dark Overlord", "malicious code", "a way of gaining unauthorized access to a network or computer system"]), "Which is the largest, weakest part of the attack surface?": (3, ["All computers in a network", "Outdated software on a computer", "People", "Weak passwords"]) } ############################################################################################################# ############################################################################################################# ############################ DO NOT EDIT BELOW CODE ############################ ############################################################################################################# ############################################################################################################# import codesters import random from codesters.demo import Demo from codesters import Text # SCROLL BUTTON EVENTS def mouse_out(sprite): for s in scroll_sprites: s.set_y_speed(0) sprite.set_outline_color("black") def click_up(sprite): for s in scroll_sprites: s.set_y_speed(0) sprite.set_outline_color("black") def mouse_over(sprite): # Disable scroll up if title.get_top() < 251: up_button.event_click(None) for s in scroll_sprites: s.set_y_speed(0) # up_button.set_outline_color("black") # Enable scroll up if title.get_top() > 251: up_button.event_click(up_click) # Disable scroll down if text_sprite.get_bottom()-500 > -225: down_button.event_click(None) for s in scroll_sprites: s.set_y_speed(0) # down_button.set_outline_color("black") # Enable scroll down if text_sprite.get_bottom()-500 < -225: down_button.event_click(down_click) def up_click(sprite): up_button.set_outline_color("orange") for s in scroll_sprites: s.set_y_speed(-scroll_speed) def down_click(sprite): down_button.set_outline_color("orange") for s in scroll_sprites: s.set_y_speed(scroll_speed) # ARROW KEY EVENTS def up_arrow(): if text_sprite.get_top() < 199: for s in scroll_sprites: s.set_y_speed(0) def down_arrow(): if text_sprite.get_bottom()-500 > -225: for s in scroll_sprites: s.set_y_speed(0) def up_arrow_press(): up_button.set_outline_color("orange") for s in scroll_sprites: s.set_y_speed(-scroll_speed) def up_arrow_release(): for s in scroll_sprites: s.set_y_speed(0) up_button.set_outline_color("black") def down_arrow_press(): down_button.set_outline_color("orange") for s in scroll_sprites: s.set_y_speed(scroll_speed) def down_arrow_release(): for s in scroll_sprites: s.set_y_speed(0) down_button.set_outline_color("black") # INTERVAL EVENT TO LIMIT SCROLLING def scroll_limiter(): # Disable scroll up if title.get_top() < 251: up_button.event_click(None) for s in scroll_sprites: s.set_y_speed(0) # up_button.set_opacity(.5) up_button.set_outline_color("black") # Enable scroll up if title.get_top() > 251: # up_button.set_opacity(1) up_button.event_click(up_click) # Disable scroll down if text_sprite.get_bottom()-500 > -225: down_button.event_click(None) for s in scroll_sprites: s.set_y_speed(0) down_button.set_outline_color("black") # Enable scroll down if text_sprite.get_bottom()-500 < -225: down_button.event_click(down_click) def stop_scrolling(): for s in scroll_sprites: s.set_y_speed(0) def disable_events(): stop_scrolling() stage.remove_all_events() stage.remove_all_sprite_events() def enable_events(): # Stage button event handlers up_button.event_click(up_click) up_button.event_click_up(click_up) down_button.event_click(down_click) down_button.event_click_up(click_up) up_button.event_mouse_over(mouse_over) up_button.event_mouse_out(mouse_out) down_button.event_mouse_over(mouse_over) down_button.event_mouse_out(mouse_out) # Up arrow key event handlers stage.event_key("up", up_arrow) stage.event_key_press("up", up_arrow_press) stage.event_key_release("up", up_arrow_release) # Down arrow key event handlers stage.event_key("down", down_arrow) stage.event_key_press("down", down_arrow_press) stage.event_key_release("down", down_arrow_release) # Scroll limiting interval event handler stage.event_interval(scroll_limiter, .1) def make_option_labels(button_list): alpha = "ABCDEF" label_list = [] for i, b in enumerate(button_list): label = codesters.Text(alpha[i]+")", -260, b.get_y()) label.set_text_align("left") label_list.append(label) return label_list def make_options(option_list): text_list = [] for o in option_list: option = Text(o, 0, offstage_below, "black") option.set_text_width(450) text_list.append(option) return text_list def make_buttons(num_options): button_colors = ["lightblue", "orange", "thistle", "lightyellow", "lightseagreen", "lightgreen"] button_list = [] for i in range(num_options): button = codesters.Rectangle(0, offstage_below, 530, 30, button_colors[i], "black") button.number = i+1 button_list.append(button) return button_list # Sets up question object with buttons, options, and labels def make_question(question, option_list): # First, remove any existing question if question_sprites: demo.remove_sprites(question_sprites) for q in question_sprites: scroll_sprites.remove(q) # Most sprites created offstage and then moved to position question_back = codesters.Rectangle(0, offstage_below, 540, 250, "white", "black") question_text = codesters.Text(question, 0, offstage_below) question_text.set_top(text_sprite.get_bottom()-50) question_text.set_text_width(530) # Create question components button_sprites = make_buttons(len(option_list)) option_sprites = make_options(option_list) # Store the bottom of the object above to place objects below it spacing_under_question_text = 25 above_bottom = question_text.get_bottom()-spacing_under_question_text # Place buttons and add option and option_label button_spacing = 5 for i, b in enumerate(button_sprites): b.set_height(option_sprites[i].get_height()+10) b.set_top(above_bottom-button_spacing) demo.add_hover_opacity_element(b) option_sprites[i].go_to(b.get_x(), b.get_y()) above_bottom = b.get_bottom() # Resize the question background and reset its position question_back.set_height((question_text.get_top()-above_bottom)+20) question_back.set_top(question_text.get_top()+10) # Add labels to each question option_label_sprites = make_option_labels(button_sprites) # Return list of question data (NOTE: some items are lists) question_data = [question_back, question_text, button_sprites, option_sprites, option_label_sprites] return question_data def add_to_score_animation(is_correct, score_text): if is_correct: animation = codesters.Text("+1", score_text.get_x() + score_text.get_width()/2 + 50, score_text.get_y(), "green") create_feedback(u"✓", "green") else: animation = codesters.Text("-1", score_text.get_x() + score_text.get_width()/2 + 50, score_text.get_y(), "red") create_feedback(u"✕", "red") animation.set_size(0.75) animation.turn_right(360) stage.wait(0.2) stage.remove_sprite(animation) def create_feedback(input, color): text = codesters.Text(input, 0, question_back.get_y(), color) opacity = 1 size = 20 for counter in range(20): opacity -= .05 size += 20 text.set_opacity(opacity) text.set_text_size(size) stage.wait(0.0001) stage.remove_sprite(text) # OPTION CLICK EVENT def option_click(sprite): global user_answer disable_events() user_answer = sprite.number demo.unpause() def answer_questions(): global user_answer, question_sprites, scroll_sprites, question_back correct_text.set_text("Correct: 0") incorrect_text.set_text("Incorrect: 0") question_number.set_text("") user_answer = None correct = 0 incorrect = 0 # Create each question for i, question in enumerate(question_to_options): question_number.set_text(str(i+1) + " / " + str(len(question_to_options))) question_data = make_question(question, question_to_options[question][1]) question_sprites = [question_data[0], question_data[1]]+question_data[2]+question_data[3]+question_data[4] question_back = question_data[0] # Enable physics and add sprites to scroll list for q in question_sprites: q.set_physics_on() scroll_sprites += question_sprites enable_events() button_list = question_data[2] for button in button_list: button.event_click(option_click) demo.pause() # Remove event from the buttons for button in button_list: button.event_click(None) demo.remove_hover_opacity_element(button) button.set_opacity(.5) # Check if user answer is correct user_correct = question_to_options[question][0] == user_answer # Correct scenario if user_correct: correct += 1 correct_text.set_text("Correct: " + str(correct)) add_to_score_animation(True, correct_text) stage.wait(1) # Incorrect scenario else: incorrect += 1 incorrect_text.set_text("Incorrect: " + str(incorrect)) add_to_score_animation(False, incorrect_text) stage.wait(1) # ALl questions answered disable_events() for sprite in question_sprites: sprite.hide() if correct == 1: feedback = codesters.Text("You got " + str(correct) + " question correct out of " + str(len(question_to_options)) + " questions in total.") else: feedback = codesters.Text("You got " + str(correct) + " questions correct out of " + str(len(question_to_options)) + " questions in total.") # Test to see if the student gets every question correct. If not, they don't pass the lesson. tester = TestManager() if correct == len(question_to_options): tester.display_success_message("Great job!") text_array = demo.remind_student_to_submit(question_back.get_x() - 180, question_back.get_y() - 100, 25) for counter in range(5): for sprite in text_array: sprite.set_opacity(.7) stage.wait(0.2) for sprite in text_array: sprite.set_opacity(1) stage.wait(0.2) else: tester.display_failure_message("Darn! Play again to get all questions correct!") demo.play_again() demo.remove_all_sprites_except([up_button, down_button]+scroll_sprites) answer_questions() # Constants stage_width = float(stage.get_stage_width()) stage_height = float(stage.get_stage_height()) offstage_below = -1000 # Use as y value to create objects below the stage # Activity settings scroll_speed = 6 # Create Demo instance demo = Demo() stage.auto_cache_off() stage.disable_all_walls() # Create title title = codesters.Text(title_text, 0, 0, "#00a8e1") title.set_text_weight("bold") title.set_text_width(700) title.set_text_size(35) title.set_top(250) # Create main text text_sprite = codesters.Text(text, 0, 0) text_sprite.set_text_size(25) text_sprite.set_text_width(600) # text_sprite.set_text_align("left") text_sprite.set_text_height(30) text_sprite.set_top(200) # Calculate document dimensions document_top = title.get_top() document_bottom = text_sprite.get_bottom() # NOTE: this is a hard limit and is not dynamic document_height = document_top - document_bottom # # # Create images # image_sprites = [] # image_x = -425 # image_width = 200 # image_spacing = document_height / len(image_labels) # image_start_y = document_top - image_spacing/2 # # Dynamically resize and space each image # for image_label in image_labels: # image = codesters.Sprite(image_label, image_x, image_start_y) # if image.get_width() > image_width: # while image.get_width() > image_width: # image.set_size(.95) # else: # while image.get_width() < image_width: # image.set_size(1.05) # image_sprites.append(image) # image_start_y -= image_spacing image1 = demo.create_sprite_off_screen("ransomware", -420, 75, .6) image2 = demo.create_sprite_off_screen("ransom_1d5", -425, -255, .5) image3 = demo.create_sprite_off_screen("worm_a5e", -425, -465, 1.3) image4 = demo.create_sprite_off_screen("stealthviris_f8b", -425, -665, 1.3) image5 = demo.create_sprite_off_screen("spyware_599", -425, -865, 1.3) image_sprites = [image1, image2, image3, image4, image5] # Scroll up/down buttons up_button = codesters.Triangle(450, 0, 100, "black") up_button.set_line_thickness(5) up_button.set_bottom(25) down_button = codesters.Triangle(450, 0, 100, "black") down_button.set_line_thickness(5) down_button.set_top(-25) down_button.set_rotation(180) # Correct and question number displays correct_text = codesters.Text("Correct: 0", -450, text_sprite.get_bottom()-150, "green") correct_text.set_text_align("left") incorrect_text = codesters.Text("Incorrect: 0", -450, text_sprite.get_bottom()-150-40, "red") incorrect_text.set_text_align("left") question_number = codesters.Text("", -450, text_sprite.get_bottom()-150+40) question_number.set_text_align("left") # Create Placeholder question question_sprites = [] question_data = make_question("Click Here to Load Questions", [" ", " ", " ", " "]) question_sprites = [question_data[0], question_data[1]]+question_data[2]+question_data[3]+question_data[4] question_back = question_data[0] # Build list of sprites that must scroll scroll_sprites = [title, text_sprite, correct_text, incorrect_text, question_number]+image_sprites+question_sprites # Turn physics on, especially for text sprites for sprite in scroll_sprites: sprite.set_physics_on() # Enable all events for first time enable_events() # Start answering questions by clicking question_back.event_click(answer_questions)
  • Run Code
  • Submit Work
  • Next Activity
  • Show Console
  • Reset Code Editor
  • Codesters How To (opens in a new tab)